package com.example.easycharge.schedule;

import com.example.easycharge.entity.Alert;
import com.example.easycharge.entity.MessageItem;
import com.example.easycharge.error.*;
import com.example.easycharge.notRepEntity.AlertTypeEnum;
import com.example.easycharge.notRepEntity.QueueStateEnum;
import com.example.easycharge.notRepEntity.WaitQueue;
import com.example.easycharge.repository.AlertRepository;
import com.example.easycharge.repository.ChargePileRepository;
import com.example.easycharge.repository.MessageItemRepository;
import com.example.easycharge.service.BillService;
import com.example.easycharge.service.ChargeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class ChargeTiming {

    @Autowired
    private ChargeService chargeService;
    @Autowired
    private BillService billService;
    @Autowired
    private MessageItemRepository messageItemRepository;
    @Autowired
    private AlertRepository alertRepository;
    @Autowired
    private ChargePileRepository chargePileRepository;

    @Scheduled(fixedDelay = 6000, initialDelay = 10000)
    public void chargeTiming() throws BillNotFoundError, QueueNotFoundError, InvalidOperateError, PileNotFoundError, ServiceNotSupport, WithoutAuthorityError {
        HashMap<Long, WaitQueue> waitQueueMap = chargeService.getWaitQueue();
        // 定时任务，每分钟将每个队列中充电的那个车时间减1
        Date nowDate = new Date();
        double overtimeMoneyPreHour = billService.getOvertimeMoneyPreHour();

        chargePileRepository.addWorkMinutes();
        for (WaitQueue waitQueue : waitQueueMap.values()) {
            if (waitQueue.getChargingVehicle() == null) {
                continue;
            }
            long vehicleId = waitQueue.getChargingVehicle().getVehicleId();
            long customerId = waitQueue.getChargingVehicle().getCustomerId();
            if (waitQueue.isCharge()) {
                waitQueue.minutesTick();
                billService.addChargeBill(vehicleId);
                chargePileRepository.addChargeMinutes(waitQueue.getPileID());
                if (waitQueue.getLeftMinutes() == 0) {
                    waitQueue.finishCharge();
                    billService.endCharge(vehicleId);
                    // 通知车主电已充满
                    MessageItem messageItem = new MessageItem(customerId, "车辆已充满电，请及时拔出充电头并驶离");
                    messageItemRepository.saveAndFlush(messageItem);
                    // TODO: 2022-06-15 临时改动
                    chargeService.finishCharge(vehicleId);
                }
            } else {
                QueueStateEnum queueState = waitQueue.getState();
                waitQueue.waitTick();
                int waitTime = waitQueue.getWaitMinutes();
                int waitLength = waitQueue.getWaitLength();
                if (queueState == QueueStateEnum.WAITING_DRIVE_IN) {
                    if (waitTime >= 30) {
                        // 移动到队尾
                        MessageItem messageItem;
                        if (waitLength == 0) {
                            messageItem = new MessageItem(customerId, "车辆长时间未驶入，请您及时驶入充电");
                        } else {
                            long nextCustomerId = waitQueue.moveToTail();
                            messageItem = new MessageItem(customerId, "车辆长时间未驶入，已将您移动至队列的末尾，请您注意预约的时间");
                        }
                        messageItemRepository.saveAndFlush(messageItem);
                    }
                } else if (queueState == QueueStateEnum.WAITING_PLUG_IN) {
                    if (waitTime > 240) {
                        // 发警报
                        Alert alert = new Alert(AlertTypeEnum.OVERTIME, "车辆：" + waitQueue.getChargingVehicle().getVehicleId() + " 在充电桩：" + waitQueue.getPileID() + " 停靠，并超过4小时未插入充电头，请及时处理");
                        alertRepository.saveAndFlush(alert);
                    }
                    if (waitTime < 720 && waitTime % 60 == 0) {
                        MessageItem messageItem = new MessageItem(customerId, "您的车辆长时间未驶离，已收取部分服务费(每小时计)，请您及时驶离");
                        billService.getBill(vehicleId).overtimeMoneyAdd(overtimeMoneyPreHour);
                        messageItemRepository.saveAndFlush(messageItem);
                    }
                } else if (queueState == QueueStateEnum.WAITING_PLUG_OFF) {
                    // 已经八小时没拔充电头了，很可能出问题了
                    if (waitTime > 480) {
                        // 发警报
                        Alert alert = new Alert(AlertTypeEnum.OVERTIME, "车辆：" + waitQueue.getChargingVehicle().getVehicleId() + " 在充电桩：" + waitQueue.getPileID() + " 已充满，并超过8小时未拔出充电头，请及时处理");
                        alertRepository.saveAndFlush(alert);
                    }
                    if (waitTime % 60 == 0 && waitTime < 600) {
                        MessageItem messageItem = new MessageItem(customerId, "您的车辆已充满，请您及时拔出充电头并驶离");
                        messageItemRepository.saveAndFlush(messageItem);
                        billService.getBill(vehicleId).overtimeMoneyAdd(overtimeMoneyPreHour);
                    }
                    billService.getBill(vehicleId).overtimeMinutesTick();
                } else if (queueState == QueueStateEnum.WAITING_DRIVE_AWAY) {
                    if (waitTime > 240) {
                        // 发警报
                        Alert alert = new Alert(AlertTypeEnum.OVERTIME, "车辆：" + waitQueue.getChargingVehicle().getVehicleId() + " 在充电桩：" + waitQueue.getPileID() + " 已充满，并超过4小时未驶离，请及时处理");
                        alertRepository.saveAndFlush(alert);
                    }
                    if (waitTime % 60 == 0 && waitLength != 0 && waitTime < 480) {
                        MessageItem messageItem = new MessageItem(customerId, "您的车辆已充满，有其他人正在等待此充电桩，请您及时驶离");
                        billService.getBill(vehicleId).overtimeMoneyAdd(overtimeMoneyPreHour);
                        messageItemRepository.saveAndFlush(messageItem);
                    }
                    billService.getBill(vehicleId).overtimeMinutesTick();
                }
            }
        }
    }

    @Scheduled(fixedDelay = 360000, initialDelay = 360000)
    public void hourAdd() {
        billService.hourAdd();
    }
}
